home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / 3dvect39 / poly.inc < prev    next >
Text File  |  1994-10-30  |  59KB  |  1,865 lines

  1. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2. ;
  3. ; Filename     : Poly.inc
  4. ; Included from: 3D1.ASM, 3D2.ASM, 3D3.ASM
  5. ; Description  : 3D xmode, polyfill and object handling routines
  6. ;
  7. ; Written by: John McCarthy
  8. ;             1316 Redwood Lane
  9. ;             Pickering, Ontario.
  10. ;             Canada, Earth, Milky Way (for those out-of-towners)
  11. ;             L1X 1C5
  12. ;
  13. ; Internet/Usenet:  BRIAN.MCCARTHY@CANREM.COM
  14. ;         Fidonet:  Brian McCarthy 1:229/15
  15. ;   RIME/Relaynet: ->CRS
  16. ;
  17. ; Home phone, (905) 831-1944, don't call at 2 am eh!
  18. ;
  19. ; John Mccarthy would really love to work for a company programming Robots
  20. ; or doing some high intensive CPU work.  Hint. Hint.
  21. ;
  22. ; Send me your protected mode source code!
  23. ; Send me your Objects!
  24. ; But most of all, Send me a postcard!!!!
  25. ;
  26. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  27.  
  28.          public _polyfill                   ; fill polygon
  29.          public _fakeline_horz              ; draw line in memory buffer
  30.          public _fakeline_vert              ; draw line in memory buffer (glenz)
  31.          public _set_clip_absolute          ; set clipping parameters - absolute
  32.          public _set_clip_offset            ; set clipping parameters - offset
  33.          public _fastimultable              ; fast imul table, dw 0-319 * 200
  34.          public _clipped_line               ; draw clipped line from dx,cx to ax,bx colour bp
  35.          public _sortlist                   ; sort vector list
  36.          public _drawvect                   ; draw vectors from command list
  37.          public _copy_virtual_objects       ; copy real objects to virtual list
  38.  
  39. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  40. ;
  41. ; _polyfill: Draws a filled polygon given table left and right addresses
  42. ;
  43. ; In:
  44. ;    Regs=none
  45. ;
  46. ; Memory - these get set up by _fakeline_horz routine
  47. ;
  48. ;    _colq - colour for polygon
  49. ;    _poly_oney - top of polygon in table (maps to y location of screen)
  50. ;    _poly_firstbyte[] - left side to begin draw
  51. ;    _poly_lastbyte[] - right side to end draw
  52. ; _current_page - current offset of video memory for page of xmode, see xmode.asm
  53. ;
  54. ; Out:
  55. ;   null
  56. ;
  57. ; Notes:
  58. ; Call _fakeline_horz to define the edges of your polygon, then call here to fill it
  59. ;
  60. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  61.  
  62.          align 4
  63. pf_done:
  64.          pop eax
  65. pf_outearly:
  66.          mov _poly_oney,1000                ; reset for next polygon call
  67.          ret
  68.  
  69.          align 4
  70. _polyfill:
  71. ;        out_8 sc_index, map_mask           ; set up for plane select
  72.  
  73.          xor eax,eax
  74.          mov ebx,_poly_oney                 ; ax=_y1
  75.          cmp bx,_ymins
  76.          jl s pf_missub
  77.  
  78.          cmp bx,_ymaxs
  79.          jge pf_outearly
  80.          sub bx,_ymins
  81.          mov ax,bx
  82. pf_missub:
  83.          mov ebp,eax                        ; indexer to line
  84.          add ebp,ebp
  85.          add ax, _cliptp
  86.  
  87.          mov edi, _current_page             ; point to active vga page
  88.          mov eax,[eax*4+_fastimultable]     ; mul _y1 by bytes per line
  89.  
  90.          add edi,eax                        ; di = start of line _y1
  91.          xor edx,edx
  92.  
  93. pf_more_lines:
  94.          push edi                           ; save right hand position
  95.          mov ax, [_poly_firstbyte+ebp]
  96.          cmp ax,_xmaxs                      ; check if fill done
  97.          jge pf_done
  98.  
  99.          xor ebx,ebx
  100.          mov bx,[_poly_lastbyte+ebp]
  101.          add ax,_xcent
  102.          add bx,_xcent
  103.  
  104.          mov edx,eax                        ; dx = _x1 (pixel position)
  105.          shr edx,2                          ; dx/4 = bytes into line
  106.          add edi,edx                        ; di = addr of upper-left corner
  107.  
  108.          mov ecx,ebx                        ; cx = _x2 (pixel position)
  109.          shr ecx,2                          ; cx/4 = bytes into line
  110.  
  111.          cmp edx,ecx                        ; start and end in same band?
  112.          jg pf_exit                         ; skip if _fakeline_horz fails connection
  113.          je pf_one_band_only                ; if so, then special processing
  114.  
  115.          mov ah,_colq                       ; get fill color
  116.          sub ecx,edx                        ; cx = # bands -1
  117.          mov esi,eax                        ; si = plane#(_x1)
  118.          and esi,plane_bits                 ; if left edge is aligned then
  119.          jz s pf_l_plane_flush              ; no special processing..
  120.  
  121. ; draw "left edge" of 1-3 pixels...
  122.  
  123.          out_8 sc_data, _left_clip_mask[esi] ; set left edge plane mask
  124.  
  125.          mov [edi], ah                      ; fill in left edge pixels
  126.  
  127.          inc edi                            ; point to middle (or right) block
  128.          dec ecx                            ; reset cx instead of jmp pf_right
  129.  
  130. pf_l_plane_flush:
  131.          inc ecx                            ; add in left band to middle block
  132.  
  133. ; di = addr of 1st middle pixel (band) to fill
  134. ; cx = # of bands to fill -1
  135.  
  136. pf_right:
  137.          mov esi,ebx                        ; get xpos2
  138.          and esi,plane_bits                 ; get plane values
  139.          cmp esi,0003                       ; plane = 3?
  140.          je s pf_r_edge_flush               ; hey, add to middle
  141.  
  142. ; draw "right edge" of 1-3 pixels...
  143.  
  144.          out_8 sc_data, _right_clip_mask[esi] ; right edge plane mask
  145.  
  146.          mov esi,edi                        ; get addr of left edge
  147.          add esi,ecx                        ; add width-1 (bands) to point to top of right edge
  148.          dec esi
  149.  
  150. pf_right_loop:
  151.          mov [esi], ah                      ; fill in right edge pixels
  152.  
  153.          dec ecx                            ; minus 1 for middle bands
  154.          jz s pf_exit                       ; uh.. no middle bands...
  155.  
  156. pf_r_edge_flush:
  157.  
  158. ; di = addr of upper left block to fill
  159. ; cx = # of bands to fill in (width)
  160.  
  161.          out_8 sc_data, all_planes          ; write to all planes
  162.  
  163.          mov dx, xactual/4                  ; dx = di increment
  164.          sub edx, ecx                       ;  = _screen_width-# planes filled
  165.  
  166.          mov al, ah                         ; colour is in high and low for stosw
  167.  
  168. pf_middle_loop:
  169.          shr ecx,1                          ; dont use doubleword transfer
  170.          rep stosw
  171.          adc cl,0
  172.          rep stosb
  173. pf_exit:
  174.          pop edi
  175.          mov d [_poly_firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  176.          mov d [_poly_lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  177.          add ebp,2
  178.          add edi,xactual/4
  179.          jmp pf_more_lines
  180.  
  181. pf_one_band_only:
  182.          cmp ax, _cliplt
  183.          jne s pf_nexit
  184.          cmp bx,ax
  185.          je s pf_exit
  186. pf_nexit:
  187.          cmp ax, _cliprt
  188.          je s pf_exit
  189.          mov esi,eax                        ; get left clip mask, save _x1
  190.          and esi,plane_bits                 ; mask out row #
  191.          mov al,_left_clip_mask[esi]        ; get left edge mask
  192.          mov esi,ebx                        ; get right clip mask, save _x2
  193.          and esi,plane_bits                 ; mask out row #
  194.          and al,_right_clip_mask[esi]       ; get right edge mask byte
  195.  
  196.          out_8 sc_data, al                  ; clip for left & right masks
  197.  
  198.          mov ah,_colq                       ; get fill color
  199.          mov [edi], ah                      ; fill in pixels
  200.          jmp s pf_exit                      ; outa here, for this line
  201.  
  202.          align 4
  203. ss_done:
  204.          pop eax
  205. ss_outearly:
  206.          mov _poly_oney,1000                ; reset for next polygon call
  207.          ret
  208.  
  209. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  210. ; SS_dosteel: Fill polygon with a sine-waved texture.  Implemented by the use
  211. ;             of the "wavey" texture option.
  212. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  213.  
  214.          align 4
  215.  
  216. ss_dosteel:
  217. ;          out_8 sc_index, map_mask ; set up for plane select
  218.  
  219.          xor eax,eax
  220.          mov ebx,_poly_oney                 ; ax=_y1
  221.          cmp bx,_ymins
  222.          jl s ss_missub
  223.  
  224.          cmp bx,_ymaxs
  225.          jge ss_outearly
  226.          sub bx,_ymins
  227.          mov ax,bx
  228. ss_missub:
  229.          mov bl,_colq                       ; yes, save colour offset and 16 block
  230.          mov steelc,bl
  231.          and steelc,0f0h                   ; save base offset of 16 colour block
  232.          shl bl,2                           ; colour offset is *2 (small) *4 (large)
  233.          add bl,al                          ; make steel always constant
  234.          sub ebx,_poly_oney                 ; *****  ; remove this line if you want sine textures to be "pegged" - eg stationary
  235.          and bl,03fh                        ; colour indexer (so sides look different)
  236.          mov steel ,bl
  237.  
  238.          mov ebp,eax                        ; indexer to line
  239.          add ebp,ebp
  240.          add ax, _cliptp
  241.  
  242.          mov edi, _current_page             ; point to active vga page
  243.          mov eax,[eax*4+_fastimultable]     ; mul _y1 by bytes per line
  244.  
  245.          add edi,eax                        ; di = start of line _y1
  246.          xor edx,edx
  247.  
  248. ss_more_lines:
  249.          push edi                           ; save right hand position
  250.          mov ax, [_poly_firstbyte+ebp]
  251.          cmp ax,_xmaxs                      ; check if fill done
  252.          jge ss_done
  253.  
  254.          xor ebx,ebx
  255.          mov bl,steel                      ; use steel texture?
  256.          mov dl,pf_updown[ebx]
  257.          add dl,steelc
  258.          mov _colq,dl
  259.          inc bl
  260.          and bl,03fh                        ; 16 colours, 32 positions for steel texture
  261.          mov steel,bl
  262.  
  263.          mov bx,[_poly_lastbyte+ebp]
  264.          add ax,_xcent
  265.          add bx,_xcent
  266.  
  267.          mov edx,eax                        ; dx = _x1 (pixel position)
  268.          shr edx,2                          ; dx/4 = bytes into line
  269.          add edi,edx                        ; di = addr of upper-left corner
  270.  
  271.          mov ecx,ebx                        ; cx = _x2 (pixel position)
  272.          shr ecx,2                          ; cx/4 = bytes into line
  273.  
  274.          cmp edx,ecx                        ; start and end in same band?
  275.          jg ss_exit                         ; skip if _fakeline_horz fails connection
  276.          je ss_one_band_only                ; if so, then special processing
  277.  
  278.          mov ah,_colq                       ; get fill color
  279.          sub ecx,edx                        ; cx = # bands -1
  280.          mov esi,eax                        ; si = plane#(_x1)
  281.          and esi,plane_bits                 ; if left edge is aligned then
  282.          jz s ss_l_plane_flush              ; no special processing..
  283.  
  284. ; draw "left edge" of 1-3 pixels...
  285.  
  286.          out_8 sc_data, _left_clip_mask[esi] ; set left edge plane mask
  287.  
  288.          mov [edi], ah                      ; fill in left edge pixels
  289.  
  290.          inc edi                            ; point to middle (or right) block
  291.          dec ecx                            ; reset cx instead of jmp ss_right
  292.  
  293. ss_l_plane_flush:
  294.          inc ecx                            ; add in left band to middle block
  295.  
  296. ; di = addr of 1st middle pixel (band) to fill
  297. ; cx = # of bands to fill -1
  298.  
  299. ss_right:
  300.          mov esi,ebx                        ; get xpos2
  301.          and esi,plane_bits                 ; get plane values
  302.          cmp esi,0003                       ; plane = 3?
  303.          je s ss_r_edge_flush               ; hey, add to middle
  304.  
  305. ; draw "right edge" of 1-3 pixels...
  306.  
  307.          out_8 sc_data, _right_clip_mask[esi] ; right edge plane mask
  308.  
  309.          mov esi,edi                        ; get addr of left edge
  310.          add esi,ecx                        ; add width-1 (bands) to point to top of right edge
  311.          dec esi
  312.  
  313. ss_right_loop:
  314.          mov [esi], ah                      ; fill in right edge pixels
  315.  
  316.          dec ecx                            ; minus 1 for middle bands
  317.          jz s ss_exit                       ; uh.. no middle bands...
  318.  
  319. ss_r_edge_flush:
  320.  
  321. ; di = addr of upper left block to fill
  322. ; cx = # of bands to fill in (width)
  323.  
  324.          out_8 sc_data, all_planes          ; write to all planes
  325.  
  326.          mov dx, xactual/4                  ; dx = di increment
  327.          sub edx, ecx                       ;  = _screen_width-# planes filled
  328.  
  329.          mov al, ah                         ; colour is in high and low for stosw
  330.  
  331. ss_middle_loop:
  332.          shr ecx,1                          ; dont use doubleword transfer
  333.          jnc s ss_ord
  334.          stosb                              ; if cx odd, store byte first
  335. ss_ord:
  336.          rep stosw
  337. ss_exit:
  338.          pop edi
  339.          mov d [_poly_firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  340.          mov d [_poly_lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  341.          add ebp,2
  342.          add edi,xactual/4
  343.          jmp ss_more_lines
  344.  
  345. ss_one_band_only:
  346.          cmp ax, _cliplt
  347.          jne s ss_nexit
  348.          cmp bx,ax
  349.          je s ss_exit
  350. ss_nexit:
  351.          cmp ax, _cliprt
  352.          je s ss_exit
  353.          mov esi,eax                        ; get left clip mask, save _x1
  354.          and esi,plane_bits                 ; mask out row #
  355.          mov al,_left_clip_mask[esi]        ; get left edge mask
  356.          mov esi,ebx                        ; get right clip mask, save _x2
  357.          and esi,plane_bits                 ; mask out row #
  358.          and al,_right_clip_mask[esi]       ; get right edge mask byte
  359.  
  360.          out_8 sc_data, al                  ; clip for left & right masks
  361.  
  362.          mov ah,_colq                       ; get fill color
  363.          mov [edi], ah                      ; fill in pixels
  364.          jmp s ss_exit                      ; outa here, for this line
  365.  
  366.          align 4
  367.  
  368. ; small steel texture, make sure to set shl bl,*1* before ss_missub:
  369.  
  370. ;pf_updown  db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  371. ;           db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
  372. ;           db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  373. ;           db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
  374.  
  375. ; large steel texture, make sure to set shl bl,*2* before ss_missub:
  376.  
  377. pf_updown db 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
  378.          db 10,10,11,11,12,12,13,13,14,14,15,15
  379.          db 15,15,14,14,13,13,12,12,11,11,10,10
  380.          db 9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0
  381.  
  382. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  383. ; WN_dowindow:  Fill polygon with a mesh style texture. This plots only every
  384. ;               other pixel.
  385. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  386.  
  387.          align 4
  388. wn_done:
  389.          pop eax
  390. wn_outearly:
  391.          mov _poly_oney,1000                ; reset for next polygon call
  392.          ret
  393.  
  394.          align 4
  395. wn_dowindow:
  396. ;          out_8 sc_index, map_mask ; set up for plane select
  397.  
  398.          xor eax,eax
  399.          mov ebx,_poly_oney                 ; ax=_y1
  400.          cmp bx,_ymins
  401.          jl s wn_missub
  402.  
  403.          cmp bx,_ymaxs
  404.          jge wn_outearly
  405.          sub bx,_ymins
  406.          mov ax,bx
  407. wn_missub:
  408.          mov ebp,eax                        ; indexer to line
  409.          add ebp,ebp
  410.          add ax, _cliptp
  411.  
  412.          mov edi, _current_page             ; point to active vga page
  413.          mov ebx,[eax*4+_fastimultable]     ; mul _y1 by bytes per line
  414.  
  415.          add edi,ebx                        ; edi = start of line _y1
  416.          xor edx,edx
  417.          and eax,1
  418.          mov al,wn_zap[eax]
  419.          mov wn_zip,al
  420.  
  421. wn_more_lines:
  422.          xor wn_zip,0fh
  423.          push edi                           ; save right hand position
  424.          mov ax, [_poly_firstbyte+ebp]
  425.          cmp ax,_xmaxs                      ; check if fill done
  426.          jge wn_done
  427.  
  428.          xor ebx,ebx
  429.          mov bx,[_poly_lastbyte+ebp]
  430.          add ax,_xcent
  431.          add bx,_xcent
  432.  
  433.          mov edx,eax                        ; dx = _x1 (pixel position)
  434.          shr edx,2                          ; dx/4 = bytes into line
  435.          add edi,edx                        ; di = addr of upper-left corner
  436.  
  437.          mov ecx,ebx                        ; cx = _x2 (pixel position)
  438.          shr ecx,2                          ; cx/4 = bytes into line
  439.  
  440.          cmp edx,ecx                        ; start and end in same band?
  441.          jg wn_exit                         ; skip if _fakeline_horz fails connection
  442.          je wn_one_band_only                ; if so, then special processing
  443.  
  444.          mov ah,_colq                       ; get fill color
  445.          sub ecx,edx                        ; cx = # bands -1
  446.          mov esi,eax                        ; si = plane#(_x1)
  447.          and esi,plane_bits                 ; if left edge is aligned then
  448.          jz s wn_l_plane_flush              ; no special processing..
  449.  
  450. ; draw "left edge" of 1-3 pixels...
  451.  
  452.          mov dx,sc_data
  453.          mov al,_left_clip_mask[esi]
  454.          and al,wn_zip
  455.          out dx,al
  456.  
  457.          mov [edi], ah                      ; fill in left edge pixels
  458.  
  459.          inc edi                            ; point to middle (or right) block
  460.          dec ecx                            ; reset cx instead of jmp wn_right
  461.  
  462. wn_l_plane_flush:
  463.          inc ecx                            ; add in left band to middle block
  464.  
  465. ; di = addr of 1st middle pixel (band) to fill
  466. ; cx = # of bands to fill -1
  467.  
  468. wn_right:
  469.          mov esi,ebx                        ; get xpos2
  470.          and esi,plane_bits                 ; get plane values
  471.          cmp esi,0003                       ; plane = 3?
  472.          je s wn_r_edge_flush               ; hey, add to middle
  473.  
  474. ; draw "right edge" of 1-3 pixels...
  475.  
  476.          mov dx,sc_data
  477.          mov al,_right_clip_mask[esi]
  478.          and al,wn_zip
  479.          out dx,al
  480.  
  481.          mov esi,edi                        ; get addr of left edge
  482.          add esi,ecx                        ; add width-1 (bands) to point to top of right edge
  483.          dec esi
  484.  
  485. wn_right_loop:
  486.          mov [esi], ah                      ; fill in right edge pixels
  487.  
  488.          dec ecx                            ; minus 1 for middle bands
  489.          jz s wn_exit                       ; uh.. no middle bands...
  490.  
  491. wn_r_edge_flush:
  492.  
  493. ; di = addr of upper left block to fill
  494. ; cx = # of bands to fill in (width)
  495.  
  496.          out_8 sc_data, wn_zip              ; write to all planes
  497.  
  498.          mov dx, xactual/4                  ; dx = di increment
  499.          sub edx, ecx                       ;  = _screen_width-# planes filled
  500.  
  501.          mov al, ah                         ; colour is in high and low for stosw
  502.  
  503. wn_middle_loop:
  504.          shr ecx,1                          ; dont use doubleword transfer
  505.          jnc s wn_ord
  506.          stosb                              ; if cx odd, store byte first
  507. wn_ord:
  508.          rep stosw
  509. wn_exit:
  510.          pop edi
  511.          mov d [_poly_firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  512.          mov d [_poly_lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  513.          add ebp,2
  514.          add edi,xactual/4
  515.          jmp wn_more_lines
  516.  
  517. wn_one_band_only:
  518.          cmp ax, _cliplt
  519.          jne s wn_nexit
  520.          cmp bx,ax
  521.          je s wn_exit
  522. wn_nexit:
  523.          cmp ax, _cliprt
  524.          je s wn_exit
  525.          mov esi,eax                        ; get left clip mask, save _x1
  526.          and esi,plane_bits                 ; mask out row #
  527.          mov al,_left_clip_mask[esi]        ; get left edge mask
  528.          mov esi,ebx                        ; get right clip mask, save _x2
  529.          and esi,plane_bits                 ; mask out row #
  530.          and al,_right_clip_mask[esi]       ; get right edge mask byte
  531.          and al,wn_zip
  532.  
  533.          out_8 sc_data, al                  ; clip for left & right masks
  534.  
  535.          mov ah,_colq                       ; get fill color
  536.          mov [edi], ah                      ; fill in pixels
  537.          jmp s wn_exit                      ; outa here, for this line
  538.  
  539. wn_zap   db 5,0ah                           ; %0101,%1010
  540. wn_zip   db 0
  541.  
  542. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  543. ; DG_doglenz:  Fill polygon with a glenz style vector.  This routine fills
  544. ;              up/down, not left/right like _polyfill.  To set up the _poly_firstbyte
  545. ;              and _poly_lastbyte tables for this routine, you must call _fakeline_vert.
  546. ;              Do not use _fakeline_horz, as _fakeline_horz fills left/right.
  547. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  548.  
  549. dg_doglenz:
  550.          xor esi,esi
  551.          xor eax,eax
  552.  
  553.          mov ebx,_poly_oney                 ; ax=_x1
  554.          cmp bx,_xmins
  555.          jl s dg_missub
  556.  
  557.          cmp bx,_xmaxs
  558.          jge wn_outearly
  559.          sub bx,_xmins
  560.          mov ax,bx
  561. dg_missub:
  562.          mov ebp,eax                        ; indexer to line
  563.          add ebp,ebp
  564.          add ax, _cliplt
  565.          mov ebx,eax
  566.  
  567. ;          out_8 sc_index,map_mask
  568.          out_8 gc_index,read_map
  569.  
  570. dg_mnloop:
  571.          mov ax, [_poly_firstbyte+ebp]
  572.          cmp ax, _ymaxs
  573.          jg s dg_doneall
  574.          mov si, [_poly_lastbyte+ebp]
  575.          sub si,ax
  576.          jz s dg_doneline
  577.  
  578.          inc ax
  579.          mov edi, _current_page             ; point to active vga page
  580.          add ax,_ycent
  581.          movzx eax,ax
  582.          add edi,[eax*4+_fastimultable]     ; mul _y1 by bytes per line
  583.  
  584.          mov ecx,ebx                        ; si = -len, bx = start, edi = screen (left)
  585.          mov eax,ebx
  586.          shr eax,2
  587.          add edi,eax
  588.  
  589.          mov al, 1                          ; map mask & plane select register
  590.          and cl, plane_bits                 ; get plane bits
  591.          shl al, cl                         ; get plane select value
  592.          out_8 sc_data, al                  ; select plane
  593.          mov al, cl
  594.          out_8 gc_index+1, al
  595.  
  596.          xor ecx,ecx
  597.          mov cl,_colq
  598.          mov ecx,[_xreftable+ecx*4]
  599.          xor eax,eax
  600.  
  601. dg_mainloop:
  602.          mov al,[edi]
  603.          mov al,[ecx+eax]
  604.          mov [edi],al
  605.          add edi,xactual/4
  606.          dec esi
  607.          jnz s dg_mainloop
  608. dg_doneline:
  609.          mov d [_poly_firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  610.          mov d [_poly_lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  611.          add ebp,2
  612.          inc ebx
  613.          jmp dg_mnloop
  614. dg_doneall:
  615.          mov _poly_oney,1000
  616.          mov leftmost,1000
  617.          ret
  618.  
  619. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  620. ; DS_dostone:  Fill polygon with a stone texture. Fill is performed
  621. ;              up/down, not left/right like _polyfill.  To set up the _poly_firstbyte
  622. ;              and _poly_lastbyte tables for this routine, you must call _fakeline_vert.
  623. ;              Do not use _fakeline_horz, as _fakeline_horz fills left/right.
  624. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  625.  
  626. ds_dostone:
  627.          xor esi,esi
  628.          xor eax,eax
  629.  
  630.          mov ebx,_poly_oney                 ; ax=_x1
  631.          cmp bx,_xmins
  632.          jl s ds_missub
  633.  
  634.          cmp bx,_xmaxs
  635.          jge wn_outearly
  636.          sub bx,_xmins
  637.          mov ax,bx
  638. ds_missub:
  639.          mov ebp,eax                        ; indexer to line
  640.          add ebp,ebp
  641.          add ax, _cliplt
  642.          mov ebx,eax
  643.  
  644.          xor ecx,ecx
  645.          mov cl,_colq
  646.          mov al,[_stoneadd+ecx]
  647.          mov _colq,al
  648.          mov ecx,[_stonetbl+ecx*4]
  649.          mov edx,[ecx]
  650.          add edx,ecx
  651.          add ecx,[ecx+4]
  652.          mov ds_ggh,edx
  653.          mov eax,_poly_oney
  654.          sub ax,_xmins
  655.          jnl s ds_nol
  656.          neg eax
  657.          cmp ax,_cliplt
  658.          jbe ds_llk
  659.          mov ax,_cliplt
  660. ds_llk:
  661.          add ecx,eax
  662. ds_nol:
  663.          xor eax,eax
  664.          mov ax,_cliplt
  665.          add ecx,eax
  666.          mov ds_yvar,ecx
  667.          mov ax,leftmost
  668.          add ax,_ycent
  669.          jnl s ds_mnloop2
  670.          xor eax,eax
  671. ds_mnloop2:
  672.          sub ds_ggh,eax
  673. ds_mnloop:
  674.          mov dx, [_poly_firstbyte+ebp]
  675.          cmp dx, _ymaxs
  676.          jg ds_doneall
  677.          mov si, [_poly_lastbyte+ebp]
  678.          sub si,dx
  679.          jle s ds_doneline
  680.  
  681.          inc dx
  682.          mov edi, _current_page             ; point to active vga page
  683.          add dx,_ycent
  684.          movzx edx,dx
  685.          add edi,[edx*4+_fastimultable]     ; mul _y1 by bytes per line
  686.  
  687.          mov ecx,ebx                        ; si = -len, bx = start, edi = screen (left)
  688.          mov eax,ebx
  689.          shr eax,2
  690.          add edi,eax
  691.  
  692.          mov al, 1                          ; map mask & plane select register
  693.          and cl, plane_bits                 ; get plane bits
  694.          shl al, cl                         ; get plane select value
  695.          mov ecx,edx
  696.          out_8 sc_data, al                  ; select plane
  697.  
  698.          mov eax,ds_yvar
  699.          movzx eax,byte ptr [eax]
  700.          add ecx,eax
  701.          add ecx,ds_ggh
  702.          mov dl,_colq
  703.  
  704. ds_mainloop:
  705.          mov al,[ecx]                       ; the stone copy loop!
  706.          add al,dl
  707.          mov [edi],al
  708.          add edi,xactual/4
  709.          inc ecx
  710.          dec esi
  711.          jnz s ds_mainloop
  712.  
  713. ds_doneline:
  714.          mov d [_poly_firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  715.          mov d [_poly_lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  716.          add ebp,2
  717.          inc ebx
  718.          inc ds_yvar
  719.          jmp ds_mnloop
  720. ds_doneall:
  721.          mov _poly_oney,1000
  722.          mov leftmost,1000
  723.          ret
  724.  
  725. ds_ggh   dd 0
  726. ds_yvar  dd 0
  727.  
  728. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  729. ;
  730. ; Table of values for fast multiplication by screen width
  731. ; eg  mov eax,[esi*4+_fastimultable] ; eax = esi*320
  732. ;
  733. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  734.  
  735. _fastimultable label dword
  736.          i=0
  737.          rept yactual
  738.          dd i*(xactual/4)
  739.          i=i+1
  740.          endm
  741.  
  742. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  743. ;
  744. ; Hey! where is my postcard! see readme.doc file and send me that postcard!
  745. ;
  746. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  747.  
  748. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  749. ;
  750. ; _fakeline_horz: Draw a line in tables _poly_firstbyte,_poly_lastbyte, adjust _poly_oney if neccessary
  751. ;
  752. ; In:
  753. ;    Regs=none
  754. ; Memory:
  755. ;    _x1 - x of line - cartisian format
  756. ;    _y1 - y of line
  757. ;    _x2 - x of line
  758. ;    _y2 - y of line
  759. ;
  760. ; Out:
  761. ;    Regs=none
  762. ;
  763. ; Notes:
  764. ;
  765. ; Line is not drawn on screen  but  is  drawn  in  memory  tables.    To  use,
  766. ; tables  must  be  clear,   (default  is    always    clear),    just    draw
  767. ; line around screen, in any order, then  call  _polyfill.  The  polygon  will
  768. ; be drawn and checked in memory, then _polyfill will plop it on  the  current
  769. ; page.  _polyfill routine clears tables during plot so tables are  ready  for
  770. ; more lines and more polygons.
  771. ;
  772. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  773.  
  774.          align 4
  775. _fakeline_horz:
  776.          mov ax,_y1
  777.          cmp _y2,ax                         ; flip order of points if drawing up
  778.          jg s okorder
  779.          mov bx,_x1
  780.          xchg bx,_x2
  781.          xchg bx,_x1
  782.          xchg ax,_y2
  783.          mov _y1,ax
  784. okorder:
  785.          movsx eax,ax
  786.          cmp eax,_poly_oney
  787.          jge s nonew_poly_oney
  788.          mov _poly_oney,eax
  789. nonew_poly_oney:
  790.  
  791.          mov ax,_x2                         ; ax=x
  792.          sub ax,_x1
  793.          mov bx,_y2                         ; bx=y
  794.          sub bx,_y1
  795.          jle sliver
  796.  
  797.          mov rise,bx
  798.          movsx ebx,bx
  799.  
  800.          shl eax,16
  801.          cdq
  802.          idiv ebx
  803.          mov ebp,eax                        ; ebp = slope*65536 (allows decimals)
  804.  
  805.          mov ax,_ymins
  806.          cmp _y1,ax                         ; check if above screen
  807.          jge s li_abov1
  808.          sub ax,_y1                         ; ax = abs(difference of ymin-_y1)
  809.          sub rise,ax                        ; dec counter
  810.          jle li_out                         ; line totally off screen
  811.  
  812.          movsx eax,ax                       ; prepare for 32bit mul
  813.          imul ebp
  814.          shr eax,16                         ; get top word
  815.          add _x1,ax                         ; set new _x1,_y1 pair
  816.          mov ax,_ymins
  817.          mov _y1,ax
  818. li_abov1:
  819.          movsx edx,_x1
  820.          shl edx,16
  821.          mov cx,rise
  822.          mov ax,_y1
  823.          movzx ebx,ax                       ; bx pointer first/_poly_lastbyte table
  824.          sub bx,_ymins
  825.          add ebx,ebx                        ; bx now word
  826.  
  827.          add eax,ecx                        ; will line go off bottom of screen?
  828.          cmp ax,_ymaxs
  829.          jl s linep                         ; no...
  830.          sub ax,_ymaxs                      ; yes, truncate cx for early exit
  831.          sub cx,ax
  832.          jle s li_out                       ; right off screen
  833. linep:
  834.          mov eax,edx
  835.          mov di,_xmins
  836.          mov si,_xmaxs1
  837.          and ecx,0000ffffh
  838.  
  839.          align 4
  840. lineloopclip:
  841.          shr edx,16                         ; main line drawing loop (clipped)
  842.  
  843.          cmp dx,di
  844.          jnge s nou
  845.          cmp dx,si
  846.          jnle s noqq
  847. noq:
  848.          cmp dx,_poly_firstbyte[ebx]        ; fix first and _poly_lastbyte table
  849.          jge s ci1
  850.          mov _poly_firstbyte[ebx],dx
  851. ci1:
  852.          cmp dx,_poly_lastbyte[ebx]
  853.          jng s ci2
  854.          mov _poly_lastbyte[ebx],dx
  855. ci2:
  856.          add eax,ebp
  857.          mov edx,eax
  858.          add ebx,2
  859.          dec ecx
  860.          jnz s lineloopclip
  861. li_out:
  862.          ret
  863. nou:
  864.          mov dx,di
  865.          jmp s noq
  866. noqq:
  867.          mov dx,si
  868.          jmp s noq
  869.  
  870.          align 4
  871. sliver:
  872.          movzx ebx,_y1                      ; bx pointer first/_poly_lastbyte table
  873.  
  874.          cmp bx,_ymaxs
  875.          jge li_out
  876.          cmp bx,_ymins                      ; clip to borders
  877.          jl li_out
  878.  
  879.          sub bx,_ymins
  880.          add ebx,ebx                        ; ebx now word
  881.  
  882.          mov cx,_x1
  883.          cmp cx,_xmins
  884.          jge s nouq1
  885.          mov cx,_xmins
  886. nouq1:
  887.          cmp cx,_xmaxs
  888.          jl s noqq1
  889.          mov cx,_xmaxs1
  890. noqq1:
  891.          cmp cx,_poly_firstbyte[ebx]        ; fix first and _poly_lastbyte table
  892.          jg s ci1q1
  893.          mov _poly_firstbyte[ebx],cx
  894. ci1q1:
  895.          cmp cx,_poly_lastbyte[ebx]
  896.          jng s ci6q1
  897.          mov _poly_lastbyte[ebx],cx
  898. ci6q1:
  899.          mov cx,_x2
  900.          cmp cx,_xmins
  901.          jge s nouq2
  902.          mov cx,_xmins
  903. nouq2:
  904.          cmp cx,_xmaxs
  905.          jl s noqq2
  906.          mov cx,_xmaxs1
  907. noqq2:
  908.          cmp cx,_poly_firstbyte[ebx]        ; fix first and _poly_lastbyte table
  909.          jg s ci1q2
  910.          mov _poly_firstbyte[ebx],cx
  911. ci1q2:
  912.          cmp cx,_poly_lastbyte[ebx]
  913.          jng s ci6q
  914.          mov _poly_lastbyte[ebx],cx
  915. ci6q:
  916.          ret
  917.  
  918.          align 4
  919.  
  920. _fakeline_vert:
  921.          mov ax,_x2
  922.          mov bx,_y2
  923.          cmp bx,leftmost
  924.          jg fg_not1
  925.          mov leftmost,bx
  926. fg_not1:
  927.          xchg _y1,ax
  928.          xchg _x1,bx
  929.          cmp ax,leftmost
  930.          jg fg_not2
  931.          mov leftmost,ax
  932. fg_not2:
  933.          mov _x2,ax
  934.          mov _y2,bx
  935.  
  936.          mov ax,_y1
  937.          cmp _y2,ax                         ; flip order of points if drawing up
  938.          jg s okorderg
  939.          mov bx,_x1
  940.          xchg bx,_x2
  941.          xchg bx,_x1
  942.          xchg ax,_y2
  943.          mov _y1,ax
  944. okorderg:
  945.          movsx eax,ax
  946.          cmp eax,_poly_oney
  947.          jge s nonew_poly_oneyg
  948.          mov _poly_oney,eax
  949. nonew_poly_oneyg:
  950.  
  951.          mov ax,_x2                         ; ax=x
  952.          sub ax,_x1
  953.          mov bx,_y2                         ; bx=y
  954.          sub bx,_y1
  955.          jle sliverg
  956.  
  957.          mov rise,bx
  958.          movsx ebx,bx
  959.  
  960.          shl eax,16
  961.          cdq
  962.          idiv ebx
  963.          mov ebp,eax                        ; ebp = slope*65536 (allows decimals)
  964.  
  965.          mov ax,_xmins
  966.          cmp _y1,ax                         ; check if above screen
  967.          jge s li_abov1g
  968.          sub ax,_y1                         ; ax = abs(difference of ymin-_y1)
  969.          sub rise,ax                        ; dec counter
  970.          jle li_outg                        ; line totally off screen
  971.  
  972.          movsx eax,ax                       ; prepare for 32bit mul
  973.          imul ebp
  974.          shr eax,16                         ; get top word
  975.          add _x1,ax                         ; set new _x1,_y1 pair
  976.          mov ax,_xmins
  977.          mov _y1,ax
  978. li_abov1g:
  979.          movsx edx,_x1
  980.          shl edx,16
  981.          mov cx,rise
  982.          mov ax,_y1
  983.          movzx ebx,ax                       ; bx pointer first/_poly_lastbyte table
  984.          sub bx,_xmins
  985.          add ebx,ebx                        ; bx now word
  986.  
  987.          add eax,ecx                        ; will line go off bottom of screen?
  988.          cmp ax,_xmaxs
  989.          jl s linepg                        ; no...
  990.          sub ax,_xmaxs                      ; yes, truncate cx for early exit
  991.          sub cx,ax
  992.          jle s li_outg                      ; right off screen
  993. linepg:
  994.          mov eax,edx
  995.          mov di,_ymins1
  996.          mov si,_ymaxs1
  997.          and ecx,0000ffffh
  998.  
  999.          align 4
  1000. lineloopg:
  1001.          shr edx,16                         ; main line drawing loop!!!
  1002.  
  1003.          cmp dx,di
  1004.          jg s noug
  1005.          mov dx,di
  1006.          jmp s noqg
  1007. noug:
  1008.          cmp dx,si
  1009.          jl s noqg
  1010.          mov dx,si
  1011. noqg:
  1012.          cmp dx,_poly_firstbyte[ebx]        ; fix first and _poly_lastbyte table
  1013.          jge s ci1g
  1014.          mov _poly_firstbyte[ebx],dx
  1015. ci1g:
  1016.          cmp dx,_poly_lastbyte[ebx]
  1017.          jng s ci2g
  1018.          mov _poly_lastbyte[ebx],dx
  1019. ci2g:
  1020.          add eax,ebp
  1021.          mov edx,eax
  1022.          add ebx,2
  1023.          dec ecx
  1024.          jnz s lineloopg
  1025. li_outg:
  1026.          ret
  1027.  
  1028.          align 4
  1029. sliverg: ret
  1030.          movzx ebx,_y1                      ; bx pointer first/_poly_lastbyte table
  1031.  
  1032.          cmp bx,_xmaxs
  1033.          jge li_outg
  1034.          cmp bx,_xmins                      ; clip to borders
  1035.          jl li_outg
  1036.  
  1037.          sub bx,_ymins
  1038.          add ebx,ebx                        ; ebx now word
  1039.  
  1040.          mov cx,_x1
  1041.          cmp cx,_ymins
  1042.          jge s nouq1g
  1043.          mov cx,_ymins
  1044. nouq1g:
  1045.          cmp cx,_ymaxs
  1046.          jl s noqq1g
  1047.          mov cx,_ymaxs1
  1048. noqq1g:
  1049.          cmp cx,_poly_firstbyte[ebx]        ; fix first and _poly_lastbyte table
  1050.          jg s ci1q1g
  1051.          mov _poly_firstbyte[ebx],cx
  1052. ci1q1g:
  1053.          cmp cx,_poly_lastbyte[ebx]
  1054.          jng s ci6q1g
  1055.          mov _poly_lastbyte[ebx],cx
  1056. ci6q1g:
  1057.          mov cx,_x2
  1058.          cmp cx,_ymins
  1059.          jge s nouq2g
  1060.          mov cx,_ymins
  1061. nouq2g:
  1062.          cmp cx,_ymaxs
  1063.          jl s noqq2g
  1064.          mov cx,_ymaxs1
  1065. noqq2g:
  1066.          cmp cx,_poly_firstbyte[ebx]        ; fix first and _poly_lastbyte table
  1067.          jg s ci1q2g
  1068.          mov _poly_firstbyte[ebx],cx
  1069. ci1q2g:
  1070.          cmp cx,_poly_lastbyte[ebx]
  1071.          jng s ci6qg
  1072.          mov _poly_lastbyte[ebx],cx
  1073. ci6qg:
  1074.          ret
  1075.  
  1076.          db " **** Hey, What are you doing ripping my code?! **** "
  1077.  
  1078. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1079. ;
  1080. ; _set_clip_absolute: Set clipping parameters - non cartisian
  1081. ;
  1082. ; In:
  1083. ;    AX - left   for clip
  1084. ;    BX - top    for clip
  1085. ;    CX - right  for clip
  1086. ;    DX - bottom for clip
  1087. ; Out:
  1088. ;    ?
  1089. ;
  1090. ; Notes:
  1091. ; Set new clipping parameters where center is in middle of points ax,bx cx,dx
  1092. ; where points are absolutes! eg (10,10) (50,50) would be a small  window  in
  1093. ; the top corner of the screen.
  1094. ;
  1095. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1096.  
  1097. _set_clip_absolute:
  1098.  
  1099.          mov si,cx                          ; calc center based on points
  1100.          sub si,ax
  1101.          shr si,1
  1102.          add si,ax
  1103.  
  1104.          mov di,dx
  1105.          sub di,bx
  1106.          shr di,1
  1107.          add di,bx
  1108.  
  1109.          sub ax,si                          ; now make points offset from center
  1110.          sub cx,si
  1111.          sub bx,di
  1112.          sub dx,di                          ; fall through to _set_clip_offset
  1113.  
  1114. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1115. ;
  1116. ; _set_clip_offset: Set clipping parameters - cartisian
  1117. ;
  1118. ; In:
  1119. ;    AX - left   for clip - in cartisian format
  1120. ;    BX - top    for clip
  1121. ;    CX - right  for clip
  1122. ;    DX - bottom for clip
  1123. ;    SI - x of screen center - in cartisian format
  1124. ;    DI - y of screen center
  1125. ; Out:
  1126. ;    ?
  1127. ;
  1128. ; Notes:
  1129. ;
  1130. ; Set new clipping parameters. does  all  pre-calculation   for  variables  and
  1131. ; resets _poly_oney, _poly_firstbyte and _poly_lastbyte table.  SI,DI is center of screen.  AX,BX
  1132. ; and CX,DX are topleft and botright points to clip to.  clipping will  include
  1133. ; minimum clip variables but will exclude maximum clip variables.  eg -160,-100
  1134. ; +160,+100, with center 160,100 are valid clip parameters.  points are offsets
  1135. ; from center, not absolutes! this allows you to have the camera looking to the
  1136. ; left or right of where the pilot/plane is moving  without  having  to  change
  1137. ; the camera angle. Note: this can only change slightly as  distortion  occures
  1138. ; with too large an offset.  Make sure to assemble the original file  with  the
  1139. ; maximum Y size you will ever need so tables are set to correct size.  You can
  1140. ; never increase the total screen Y  clipping  beyond  the  original  assembley
  1141. ; restraints, but you can create any sized smaller windows.
  1142. ;
  1143. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1144.  
  1145. _set_clip_offset:
  1146.          mov bp,dx
  1147.          sub bp,bx
  1148.          cmp bp,ymax-ymin                   ; check input parameters with assembley restraints
  1149.          jg you_must_assemble_original_file_with_larger_clipping_parameters_to_achieve_this
  1150.  
  1151.          mov _xmins,ax
  1152.          mov _xmaxs,cx
  1153.          mov _ymins,bx
  1154.          mov _ymaxs,dx
  1155.          mov _xcent,si
  1156.          mov _ycent,di
  1157.  
  1158.          mov _cliptp,di
  1159.          add _cliptp,bx
  1160.  
  1161.          mov _ycentp1,di
  1162.          inc _ycentp1
  1163.  
  1164.          mov _ycents1,di
  1165.          dec _ycents1
  1166.  
  1167.          mov _clipbt,di
  1168.          add _clipbt,dx
  1169.          dec _clipbt
  1170.  
  1171.          mov _cliplt,si
  1172.          add _cliplt,ax
  1173.  
  1174.          mov _cliprt,si
  1175.          add _cliprt,cx
  1176.          dec _cliprt
  1177.  
  1178.          mov xmaxxcent,si
  1179.          add xmaxxcent,cx
  1180.  
  1181.          mov ymaxycent,di
  1182.          add ymaxycent,dx
  1183.  
  1184.          mov _xmins1,ax
  1185.          dec _xmins1
  1186.  
  1187.          mov _xmaxs1,cx
  1188.          dec _xmaxs1
  1189.  
  1190.          mov _ymins1,bx
  1191.          dec _ymins1
  1192.  
  1193.          mov _ymaxs1,dx
  1194.          dec _ymaxs1
  1195.  
  1196.          movsx eax,ax
  1197.          movsx ebx,bx
  1198.          movsx ecx,cx
  1199.          movsx edx,dx
  1200.  
  1201.          mov xmit,eax
  1202.          mov xmat,ecx
  1203.          mov ymit,ebx
  1204.          mov ymat,edx
  1205.  
  1206.          sub xmit,tolerance
  1207.          add xmat,tolerance
  1208.          sub ymit,tolerance
  1209.          add ymat,tolerance
  1210.  
  1211. you_must_assemble_original_file_with_larger_clipping_parameters_to_achieve_this:
  1212.          ret
  1213.  
  1214.          align 4
  1215.  
  1216. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1217. ; _drawvect: Draw vectors from sides list.
  1218. ; In=Out=null
  1219. ;
  1220. ; Notes:
  1221. ; Number of "sides" is "_showing".  Commands are in "textures" lists.  All
  1222. ; of this is set up by Load_points and Loadsides routines.
  1223. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1224.  
  1225. dv_none2:
  1226.          ret
  1227. _drawvect:
  1228.          cmp _showing,0                     ; no sides visible?
  1229.          je s dv_none2
  1230.  
  1231.          mov whichside,0                    ; start at side 0
  1232.          mov ebp,order[0]                   ; indexer to sides
  1233. dv_loop2:
  1234.          test textures[ebp],line+himap+point+texture+glenz ; test if line, point, scalable bitmap or bitmapped texture
  1235.          jnz dv_testit                      ; yes, do other routine
  1236.  
  1237.          mov polytype,offset _fakeline_horz
  1238. dv_contq:
  1239.          shl ebp,mult
  1240.          mov dx,sides[ebp]                  ; first point is end flag
  1241.          mov fex,dx
  1242. dv_loop1:
  1243.          movzx esi,sides[ebp]               ; get point, shl 1 not needed, pre-shl'ed
  1244.          mov eax,[xp+esi]
  1245.          mov ebx,[yp+esi]
  1246.          mov _x1,ax
  1247.          mov _y1,bx
  1248.  
  1249.          mov si,[sides+ebp+2]               ; get next point
  1250.  
  1251.          cmp si,fex                         ; test if last = first, therefore done
  1252.          pushf
  1253.  
  1254.          mov eax,[xp+esi]
  1255.          mov ebx,[yp+esi]
  1256.  
  1257.          mov _x2,ax
  1258.          mov _y2,bx
  1259.  
  1260.          push ebp
  1261.          call [polytype]                    ; draw next line
  1262.          pop ebp
  1263.  
  1264.          add ebp,2                          ; bump to next pointer now
  1265.          popf                               ; was this point equal to the first point?
  1266.          jne s dv_loop1                     ; no, draw more lines
  1267.  
  1268.          mov esi,whichside                  ; set colour for this side
  1269.          mov esi,order[esi]
  1270.          mov al,b surfcolors[esi]
  1271.          mov _colq,al
  1272.  
  1273.          xor ecx,ecx
  1274.          mov cl,byte ptr textures[esi+1]    ; use register which we can access low byte
  1275.          and cl,7
  1276.          call [polyjumps+ecx*4]
  1277. dv_return:
  1278.          add whichside,4                    ; bump bp to next block of points
  1279.          mov ebp,whichside
  1280.          mov ebp,order[ebp]                 ; get sort order
  1281.          dec _showing                       ; count for all sides
  1282.          jne dv_loop2
  1283. dv_none:
  1284.          ret
  1285.  
  1286. polyjumps dd offset _polyfill               ; 0             ; solid fill
  1287.          dd offset wn_dowindow              ; 256           ; mesh
  1288.          dd offset ss_dosteel              ; 512           ; sine wave
  1289.          dd offset 0                        ; 512+256
  1290.          dd offset dg_doglenz               ; 1024          ; glenz vector
  1291.          dd offset ds_dostone               ; 1024+256      ; stone texture
  1292.          dd offset 0                        ; 1024+512
  1293.          dd offset 0                        ; 1024+512+256
  1294. dv_assinez:
  1295.          mov polytype,offset _fakeline_vert
  1296.          jmp dv_contq
  1297.  
  1298.          align 4
  1299. dv_testit:
  1300.          mov ax,textures[ebp]               ; perform command, return to dv_return
  1301.          test eax,glenz
  1302.          jnz dv_assinez
  1303.          test eax,line
  1304.          jnz dv_doline
  1305.          test eax,point
  1306.          jnz dv_dopoint
  1307.          test eax,texture
  1308.          jnz dv_texture
  1309.  
  1310. ; draw bitmap at location x,y,z
  1311.  
  1312.          shl ebp,mult
  1313.          push eax ebp
  1314.  
  1315.          movzx ebx,w [sides+4+ebp]
  1316.          movzx ecx,w [sides+6+ebp]
  1317.  
  1318.          movzx esi,[sides+2+ebp]
  1319.          shl esi,2                          ; si = dword
  1320.          add ebx,_bitx[esi]
  1321.          add ecx,_bity[esi]                 ; ebx,ecx = top corner of _bitmap in 3d
  1322.  
  1323.          mov eax,_bitbase[esi]
  1324.          mov _bitmap,eax
  1325.  
  1326.          mov si,[sides+0+ebp]
  1327.          mov ebp,[zp+esi]
  1328.  
  1329.          call _make3d                       ; ebx,ecx = difference from center
  1330.  
  1331.          pop ebp
  1332.  
  1333.          movzx esi,[sides+0+ebp]   ; get point
  1334.          mov eax,[xp+esi]
  1335.          mov ebp,[yp+esi]
  1336.  
  1337.          sub ax,bx              ; bx = x width/2  ax, bp = top corner
  1338.          sub bp,cx              ; cx = y height/2
  1339.  
  1340.          add ax,_xcent
  1341.          add bp,_ycent
  1342.          mov _scale_destx,ax
  1343.          mov _scale_desty,bp
  1344.  
  1345.          add bx,bx
  1346.          add cx,cx
  1347.  
  1348.          mov _scale_destwidth,bx
  1349.          mov _scale_destheight,cx
  1350.  
  1351.          pop eax
  1352.          test al,lomap-himap                ; test to use 1/4 scale _bitmap or full scale
  1353.          jz s noq19
  1354.  
  1355.          call _xscale4
  1356.          jmp dv_return
  1357.  
  1358.          align 4
  1359. noq19:
  1360.          call _xscale2
  1361. noq7:
  1362.          jmp dv_return
  1363.  
  1364.          align 4
  1365.  
  1366. dv_dopoint:
  1367.          mov dx,surfcolors[ebp]             ; get colour of point
  1368.  
  1369.          shl ebp,mult
  1370.          movzx esi,[sides+ebp]              ; get point x,y
  1371.          mov ebx,[xp+esi]
  1372.          mov ecx,[yp+esi]
  1373.  
  1374.          cmp bx,_xmins                      ; check if on screen
  1375.          jl s noq7
  1376.          cmp bx,_xmaxs
  1377.          jge s noq7
  1378.          cmp cx,_ymins
  1379.          jl s noq7
  1380.          cmp cx,_ymaxs                      ; _ymaxs1 if larger pixel
  1381.          jge s noq7
  1382.  
  1383.          mov edi, _current_page             ; point to active vga page
  1384.  
  1385.          add bx,_xcent
  1386.          add cx,_ycent
  1387.  
  1388.          mov bp,dx                          ; save colour
  1389.  
  1390.          mov si,cx
  1391.          mov eax,[esi*4+_fastimultable]     ; get offset to start of line
  1392.  
  1393.          mov cx, bx                         ; copy to extract plane # from
  1394.          shr bx, 2                          ; x offset (bytes) = xpos/4
  1395.          add bx, ax                         ; offset = width*ypos + xpos/4
  1396.  
  1397.          mov ax, map_mask_plane1            ; map mask & plane select register
  1398.          and cl, plane_bits                 ; get plane bits
  1399.          shl ah, cl                         ; get plane select value
  1400.          out_16 sc_index, ax                ; select plane
  1401.  
  1402.          and ebx,0000ffffh
  1403.          mov ax,bp                          ; re-get colour
  1404.          mov [edi+ebx],al                   ; draw pixel, low is top, high is bottom
  1405. ;          add edi,xactual/4
  1406. ;          mov [edi+ebx],ah        ; draw larger bullet/pixel (high byte)
  1407.  
  1408. ; if drawing larger pixel, change above code to this!
  1409. ;          cmp cx,_ymaxs1
  1410. ;          jge s noa7
  1411.  
  1412.          jmp dv_return
  1413.  
  1414.          align 4
  1415.  
  1416. ; handle line command from _drawvect, uses _clipped_line routine
  1417.  
  1418. dv_doline:
  1419.          mov edi,ebp                        ; save...
  1420.          mov bp,surfcolors[ebp]
  1421.  
  1422.          shl edi,mult
  1423.          movzx esi,[sides+edi]              ; get first point
  1424.          mov edx,[xp+esi]
  1425.          mov ecx,[yp+esi]
  1426.  
  1427.          mov si,[sides+edi+2]               ; second point indexer
  1428.  
  1429.          mov eax,[xp+esi]                   ; now load up second point
  1430.          mov ebx,[yp+esi]
  1431.  
  1432.          call _clipped_line
  1433.          jmp dv_return                      ; return to _drawvect
  1434.  
  1435. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1436. ; _clipped_line: Draw clipped line in cartesian format from (dx,cx) to (ax,bx)
  1437. ;               using colour bp
  1438. ; In:
  1439. ;   AX - _x2
  1440. ;   BX - _y2
  1441. ;   CX - _y1
  1442. ;   DX - _x1
  1443. ;   BP - Colour
  1444. ;  _current_page - current screen start location
  1445. ; Out:null
  1446. ;
  1447. ; Similar routine to _fakeline_horz but faster,  more accurate and draws directly
  1448. ; to screen (_current_page).  Routine updates clearing borders (if used)
  1449. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1450.  
  1451. _clipped_line:
  1452.          cmp bx,cx                          ; flip order of points if drawing up
  1453.          jg s r_okorder
  1454.          xchg bx,cx
  1455.          xchg ax,dx
  1456. r_okorder:
  1457.          mov _x1,dx
  1458.          mov _y1,cx
  1459.          mov _x2,ax
  1460.          mov _y2,bx
  1461.  
  1462.          sub ax,dx
  1463.          sub bx,cx
  1464.  
  1465.          mov dx,bp
  1466.          mov _colq,dl
  1467.  
  1468.          mov dx,_ymaxs
  1469.          cmp _y1,dx
  1470.          jge cl_return
  1471.  
  1472.          mov rise,bx
  1473.          movsx ebx,bx
  1474.          or ebx,ebx
  1475.          jne s r_nsliver
  1476.  
  1477.          mov bx, _y1
  1478.          cmp bx, _ymins                     ; draw sliver, avoid divide by zero
  1479.          jl cl_return
  1480.          cmp bx, dx                         ; dx = ymax
  1481.          jge cl_return
  1482.  
  1483.          add bx,_ycent
  1484.          movzx esi,bx
  1485.          mov eax,[esi*4+_fastimultable]     ; get offset to start of line
  1486.          mov edi, _current_page
  1487.          add edi, eax                       ; edi = starting y location
  1488.  
  1489.          mov rise,1
  1490.  
  1491.          mov dx, _x1                        ; from here...
  1492.          mov si, _x2                        ;            ..to here
  1493.  
  1494.          cmp si,_xmins
  1495.          jge s u_nou3
  1496.          mov si,_xmins
  1497. u_nou3:
  1498.          cmp si,_xmaxs
  1499.          jl s u_noq3
  1500.          mov si,_xmaxs1
  1501. u_noq3:
  1502.          jmp r_splint                       ; re-enter draw later in code
  1503.  
  1504.          align 4
  1505. r_nsliver:
  1506.          shl eax,16
  1507.          cdq
  1508.          idiv ebx
  1509.          mov ebp,eax                        ; ebp = slope*65536 (allows decimals)
  1510.  
  1511.          mov ax,_ymins
  1512.          cmp _y1,ax                         ; check if above screen
  1513.          jge s r_li_abov1
  1514.          sub ax,_y1                         ; ax = abs(difference of ymin-_y1)
  1515.          sub rise,ax                        ; dec counter
  1516.          jle cl_return                      ; line totally off screen
  1517.  
  1518.          movsx eax,ax                       ; prepare for 32bit mul
  1519.          imul ebp
  1520.          shr eax,16                         ; get top word
  1521.          add _x1,ax                         ; set new _x1,_y1 pair
  1522.          mov ax,_ymins
  1523.          mov _y1,ax
  1524.  
  1525. r_li_abov1:
  1526.          mov bx,_y1                         ; bx distance from top of screen
  1527.          add bx,_ycent
  1528.          movzx esi,bx                       ; calculate screen address
  1529.          mov eax,[esi*4+_fastimultable]     ; get offset to start of line
  1530.          mov edi, _current_page
  1531.          add edi,eax                        ; edi = starting y location
  1532.  
  1533.          movsx edx,_x1
  1534.          shl edx,16
  1535.          mov cx,rise
  1536.          mov ax,_y1
  1537.          add ax,cx                          ; will line go off bottom of screen?
  1538.          cmp ax,_ymaxs
  1539.          jl s r_linep                       ; no...
  1540.          sub ax,_ymaxs                      ; yes, truncate cx for early exit
  1541.          sub rise,ax
  1542.          jle cl_return
  1543. r_linep:
  1544.          mov eax,edx
  1545.          and ecx,0000ffffh
  1546.  
  1547.          mov esi,edx
  1548.          shr esi,16
  1549.  
  1550.          cmp si,_xmins
  1551.          jge s r_nou
  1552.          mov si,_xmins
  1553. r_nou:
  1554.          cmp si,_xmaxs
  1555.          jl s r_noq
  1556.          mov si,_xmaxs1
  1557.  
  1558.          align 4
  1559. r_noq:
  1560.  
  1561. r_lineloop:
  1562.          add eax,ebp                        ; main line drawing loop!!! (for lines)
  1563.          mov edx,eax
  1564.          shr edx,16
  1565. r_splint:
  1566.          cmp dx,_xmins
  1567.          jge s u_nou
  1568.          mov dx,_xmins
  1569.          cmp dx,si
  1570.          je r_mis
  1571. u_nou:
  1572.          cmp dx,_xmaxs
  1573.          jl s u_noq
  1574.          mov dx,_xmaxs1
  1575.          cmp dx,si
  1576.          je r_mis
  1577. u_noq:
  1578.          push edx edi ebp eax               ; save for next line
  1579.          cmp dx,si
  1580.          jle s r_no_switch
  1581.          xchg dx,si
  1582. r_no_switch:
  1583.  
  1584.          add dx,_xcent
  1585.          add si,_xcent
  1586.  
  1587.          mov ax,dx
  1588.          mov bx,si
  1589.          mov _x2,si
  1590.  
  1591.          movzx edx,dx
  1592.          shr edx,2                          ; dx/4 = bytes into line
  1593.          add edi,edx                        ; di = addr of upper-left corner
  1594.          movzx ecx,bx                       ; cx = _x2 (pixel position)
  1595.          shr ecx,2                          ; cx/4 = bytes into line
  1596.  
  1597.          cmp dx,cx                          ; start and end in same band?
  1598.          je rf_one_band_only                ; if so, then special processing
  1599.  
  1600.          sub cx,dx                          ; cx = # bands -1
  1601.          mov esi,eax                        ; si = plane#(_x1)
  1602.          and esi,plane_bits                 ; if left edge is aligned then
  1603.          jz s rf_l_plane_flush              ; no special processing..
  1604.  
  1605. ; draw "left edge" of 1-3 pixels...
  1606.  
  1607.          out_8 sc_data, _left_clip_mask[esi] ; set left edge plane mask
  1608.  
  1609.          mov al,_colq                       ; get fill color
  1610.          mov [edi], al                      ; fill in left edge pixels
  1611.  
  1612.          inc edi                            ; point to middle (or right) block
  1613.          dec ecx                            ; reset cx instead of jmp s rf_right
  1614.  
  1615. rf_l_plane_flush:
  1616.          inc ecx                            ; add in left band to middle block
  1617.  
  1618. ; di = addr of 1st middle pixel (band) to fill
  1619. ; cx = # of bands to fill -1
  1620.  
  1621. rf_right:
  1622.          mov esi,ebx                        ; get xpos2
  1623.          and esi,plane_bits                 ; get plane values
  1624.          cmp esi,0003                       ; plane = 3?
  1625.          je s rf_r_edge_flush               ; hey, add to middle
  1626.  
  1627. ; draw "right edge" of 1-3 pixels...
  1628.  
  1629.          out_8 sc_data, _right_clip_mask[esi] ; right edge plane mask
  1630.  
  1631.          mov esi,edi                        ; get addr of left edge
  1632.          add esi,ecx                        ; add width-1 (bands) to point to top of right edge
  1633.          dec esi
  1634.  
  1635.          mov al,_colq                       ; get fill color
  1636.  
  1637. rf_right_loop:
  1638.          mov [esi], al                      ; fill in right edge pixels
  1639.  
  1640.          dec ecx                            ; minus 1 for middle bands
  1641.          jz rf_exit                         ; uh.. no middle bands...
  1642.  
  1643. rf_r_edge_flush:
  1644.  
  1645. ; di = addr of upper left block to fill
  1646. ; cx = # of bands to fill in (width)
  1647.  
  1648.          out_8 sc_data, all_planes          ; write to all planes
  1649.  
  1650.          mov edx, xactual/4                 ; dx = di increment
  1651.          sub edx, ecx                       ;  = _screen_width-# planes filled
  1652.  
  1653.          mov al, _colq                      ; get fill color
  1654.          mov ah, al                         ; colour is in high and low for stosw
  1655.          push ax                            ; make colour 32 bit
  1656.          shl eax,16
  1657.          pop ax
  1658.  
  1659. rf_middle_loop:
  1660.          shr ecx,1                          ; use doubleword transfer
  1661.          jnc s rf_ord
  1662.          stosb                              ; if cx odd, store byte first
  1663. rf_ord:
  1664.          rep stosw
  1665.          jmp s rf_exit                      ; outa here, for this line
  1666.  
  1667. rf_one_band_only:
  1668.          mov esi,eax                        ; get left clip mask, save _x1
  1669.          and esi,plane_bits                 ; mask out row #
  1670.          mov al,_left_clip_mask[esi]        ; get left edge mask
  1671.          mov esi,ebx                        ; get right clip mask, save _x2
  1672.          and esi,plane_bits                 ; mask out row #
  1673.          and al,_right_clip_mask[esi]       ; get right edge mask byte
  1674.  
  1675.          out_8 sc_data, al                  ; clip for left & right masks
  1676.  
  1677.          mov al, _colq                      ; get fill color
  1678.          mov [edi], al                      ; fill in pixels
  1679. rf_exit:
  1680.          pop eax ebp edi esi                ; pop screen left address
  1681. r_mis:
  1682.          add edi, xactual/4
  1683.          dec rise
  1684.          jg r_lineloop
  1685.  
  1686. cl_return:
  1687.          ret
  1688.  
  1689.          align 4
  1690. dv_texture:
  1691.          ;movzx ebx,surfcolors[ebp]
  1692.          ;mov eax,_bitbase[ebx*4]
  1693.          ;mov _scaled_texture_bitmap_offset,eax
  1694.          ;
  1695.          ;shl ebp,mult
  1696.          ;
  1697.          ;mov bx,[sides+0+ebp]
  1698.          ;mov ax,xp[ebx]
  1699.          ;mov bx,yp[ebx]
  1700.          ;mov _tex_xorg+0,ax
  1701.          ;mov _tex_yorg+0,bx
  1702.          ;
  1703.          ;mov bx,[sides+2+ebp]
  1704.          ;mov ax,xp[ebx]
  1705.          ;mov bx,yp[ebx]
  1706.          ;mov _tex_xorg+2,ax
  1707.          ;mov _tex_yorg+2,bx
  1708.          ;
  1709.          ;mov bx,[sides+4+ebp]
  1710.          ;mov ax,xp[ebx]
  1711.          ;mov bx,yp[ebx]
  1712.          ;mov _tex_xorg+4,ax
  1713.          ;mov _tex_yorg+4,bx
  1714.          ;
  1715.          ;mov bx,[sides+6+ebp]
  1716.          ;mov ax,xp[ebx]
  1717.          ;mov bx,yp[ebx]
  1718.          ;mov _tex_xorg+6,ax
  1719.          ;mov _tex_yorg+6,bx
  1720.          ;
  1721.          ;call _tex_drawtexturemap          ; not implemented yet!
  1722.  
  1723.          jmp dv_return
  1724.  
  1725. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1726. ; _sortlist:  Bubble sort for sides
  1727. ; In=Out=null
  1728. ;
  1729. ; Sort is not  perfect   since  many  sides  can  use  the  same  point.
  1730. ; If this point is the first point in the list and therefore zeds[] uses
  1731. ; the same point for sort, the routine may mess up when plotting at some
  1732. ; acute angles.  If you ever notice this, you are way  too  picky.   You
  1733. ; could fix this by adjusting the load_sides routine to search  for  the
  1734. ; closest z point.
  1735. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1736.  
  1737.          align 4
  1738.  
  1739. _sortlist dd o shell_sort                   ; offset to requested sort type
  1740.  
  1741. minusd   equ offset zeds - offset order
  1742.  
  1743. shell_sort:
  1744.          mov  ebx,_showing
  1745.  
  1746.          align 4
  1747. mainwhile:
  1748.          shr  ebx,1
  1749.          mov  ebp,ebx
  1750.          shl  ebp,2
  1751.  
  1752.          align 4
  1753. while_inner:
  1754.          xor  edx,edx
  1755.          mov  esi,o zeds
  1756.          mov  ecx,_showing
  1757.          sub  ecx,ebx
  1758.  
  1759.          align 4
  1760. forloop: mov  eax,[esi]
  1761.          cmp  [esi+ebp],eax
  1762.          jle  nextfor
  1763.  
  1764.          xchg eax,[esi+ebp]
  1765.          mov  [esi],eax
  1766.  
  1767.          mov  eax,[esi - minusd]
  1768.          xchg eax,[esi - minusd + ebp]
  1769.          mov  [esi - minusd],eax
  1770.  
  1771.          mov  edx,1
  1772.  
  1773.          align 4
  1774. nextfor: add  esi,4
  1775.          loop forloop
  1776.  
  1777.          cmp  edx,1
  1778.          je  while_inner
  1779.  
  1780.          cmp  ebx,1
  1781.          jne   mainwhile
  1782.          ret
  1783.  
  1784.          align 4
  1785. bubble_sort:
  1786.          xor  edx,edx
  1787.          mov  esi,o zeds
  1788.          mov  ecx,_showing
  1789.          dec  ecx
  1790.  
  1791.          align 4
  1792. bforloop:mov  eax,[esi]
  1793.          cmp  [esi+4],eax
  1794.          jle  bnextfor
  1795.  
  1796.          xchg eax,[esi+4]
  1797.          mov  [esi],eax
  1798.  
  1799.          mov  eax,[esi - minusd]
  1800.          xchg eax,[esi - minusd + 4]
  1801.          mov  [esi - minusd],eax
  1802.  
  1803.          mov  edx,1
  1804.  
  1805.          align 4
  1806. bnextfor:add  esi,4
  1807.          loop bforloop
  1808.  
  1809.          cmp  edx,1
  1810.          je  bubble_sort
  1811.  
  1812.          ret
  1813.  
  1814. selection_sort:
  1815.          mov esi,_showing
  1816.          cmp esi,3                          ; if only one surface, exit
  1817.          jbe qke
  1818.  
  1819.          shl esi,2                          ; esi = dword
  1820.          add esi,o order
  1821.  
  1822.          align 4
  1823. nextcx:
  1824.          sub esi,4                          ; point to last word in order[] table
  1825.  
  1826.          mov ebp,esi                        ; set order pointer
  1827.          mov ebx,d [esi]                    ; get order[si]
  1828.  
  1829.          mov edi,esi
  1830.          add edi,minusd
  1831.          mov ecx,d [edi]                    ; get zeds[si]
  1832.  
  1833.          align 4
  1834. nextdx:
  1835.          sub edi,4
  1836.          sub ebp,4
  1837.  
  1838.          cmp ecx,d [edi]                    ; zeds is point from side, should be max z
  1839.          jle s donothing
  1840.          xchg ecx,d [edi]                   ; don't flip entire side, just indexers to it
  1841.          xchg ebx,d [ebp]
  1842. donothing:
  1843.          cmp ebp,o order                    ; check bp = 0
  1844.          jne s nextdx
  1845.  
  1846.          mov [esi + minusd],ecx
  1847.          mov [esi],ebx
  1848.  
  1849.          cmp esi,o order + 4
  1850.          jne s nextcx
  1851. qke:
  1852.          ret
  1853. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1854. ; Copy real objects to virtual objects.  You MUST call this routine before
  1855. ; you draw your objects or they will be in the same place as last time.
  1856. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1857.  
  1858. _copy_virtual_objects:
  1859.          mov edi,o v_whatshape
  1860.          mov esi,o _whatshape
  1861.          mov ecx,((2+2+2+4+4+4+2+2+2+1+1+1)*(maxobjects+1)+4)/4
  1862.          rep movsd
  1863.          ret
  1864.  
  1865.